// Copyright (C) 2023 即时通讯网(52im.net) & Jack Jiang.
// The RainbowChat Project. All rights reserved.
// 
// 【本产品为著作权产品，合法授权后请放心使用，禁止外传！】
// 【本次授权给：<北京小羊驼科技有限公司>，授权编号：<NT231212144350>，代码指纹：<A.702363430.550>，技术对接人微信：<ID: wxid_wbyootvkdcgj22>】
// 【授权寄送：<收件：苏先生、地址：北京市大兴区北京密码西区6号楼1单元301、电话：18613885610、邮箱：bd@huiyuanxiang-inc.com>】
// 
// 【本系列产品在国家版权局的著作权登记信息如下】：
// 1）国家版权局登记名(简称)和权证号：RainbowChat    （证书号：软著登字第1220494号、登记号：2016SR041877）
// 2）国家版权局登记名(简称)和权证号：RainbowChat-Web（证书号：软著登字第3743440号、登记号：2019SR0322683）
// 3）国家版权局登记名(简称)和权证号：RainbowAV      （证书号：软著登字第2262004号、登记号：2017SR676720）
// 4）国家版权局登记名(简称)和权证号：MobileIMSDK-Web（证书号：软著登字第2262073号、登记号：2017SR676789）
// 5）国家版权局登记名(简称)和权证号：MobileIMSDK    （证书号：软著登字第1220581号、登记号：2016SR041964）
// * 著作权所有人：江顺/苏州网际时代信息科技有限公司
// 
// 【违法或违规使用投诉和举报方式】：
// 联系邮件：jack.jiang@52im.net
// 联系微信：hellojackjiang
// 联系QQ号：413980957
// 授权说明：http://www.52im.net/thread-1115-1-1.html
// 官方社区：http://www.52im.net
package com.x52im.rbchat.logic.main.mainimpl;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;

import com.eva.android.AppManager;
import com.eva.android.widget.ActivityRoot;
import com.king.zxing.CameraScan;
import com.x52im.rbchat.MyApplication;
import com.x52im.rbchat.logic.chat_friend.utils.ObserverFactory;
import com.x52im.rbchat.logic.main.LoginActivity;
import com.x52im.rbchat.logic.qrcode.QRCodeScanActivity;
import com.x52im.rbchat.service.GeniusService;
import com.x52im.rbchat.utils.ActivityRequestCode;

import java.util.Observer;

/**
 * APP的主Activity父类（此类中封装了：APP从音视频等JNI层库崩溃的自救重启逻辑、前台服务绑定逻辑）。
 * <p>
 * 之所以为MainActivity提炼一层父类，目的是让一些附带代码能尽量不干扰UI相关的功能代码，直白了说，就是让主界
 * 面的代码更容易理解啦，再怎么说也比所有代码放一个类里一锅烩要友好一些。
 *
 * @author JackJiang
 * @since 8.0
 */
public class AbstractMainActivity extends ActivityRoot {

    private final static String TAG = AbstractMainActivity.class.getSimpleName();

    /** 视频聊天请求全局观察者. */
    private Observer viodeoChatRequestObserver = new ObserverFactory.ViodeoChatRequestObserver(this);
    /** 实时语音聊天请求全局观察者. */
    private Observer realTimeVoiceChatRequestForNotIntChatUIObserver = new ObserverFactory.RealTimeVoiceChatRequestForNotIntChatUIObserver(this);

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //----------------------------- APP 异常自救代码 START
        if(this.appHearthCheckInvalid())
            return;
        //----------------------------- APP 异常自救代码 END

        // 添加到RainbowChar的Activity管理器栈中（以便APP退出时即时释放）
        AppManager.getAppManager().addActivity(this);
        //启动后台服务
        doBindService();
    }

    @Override
    protected void onResume() {
        initObservers();
        super.onResume();
    }

    /**
     * 一些回调通知。
     *
     * @param requestCode 请求码
     * @param resultCode 结果码
     * @param data 数据
     */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(resultCode == RESULT_OK && data!=null){
            switch (requestCode){
                // 从2维码扫描界面返回的结果回调
                case ActivityRequestCode.REQUEST_CODE_FOR_QRCODE_SCAN:
                    String result = CameraScan.parseScanResult(data);
                    Log.v(TAG, "2维码扫码结果："+result);
                    // 开始解析2维码内容并进入相应的处理逻辑
                    QRCodeScanActivity.processQRCodeScanResult(this, result);
                    break;
            }
        }
    }

    private void initObservers() {
        // 设置视频聊天请求观察者：为何要使用观察者？理由与类{@link VideoActivity.BaseEventForVideoChatObserver}相似。
        imc().getTransDataListener().setViodeoChatRequestObserver(viodeoChatRequestObserver);
        // 设置实时语音聊天请求观察者： 为何要使用观察者？理由与类{@link VideoActivity.BaseEventForVideoChatObserver}相似。
        imc().getTransDataListener().setRealTimeVoiceChatRequestForNotIntChatUIObserver(realTimeVoiceChatRequestForNotIntChatUIObserver);
    }

    private void clearObservers() {
        // 取消视频聊天请求观察者
        imc().getTransDataListener().setViodeoChatRequestObserver(null);
        // 取消实时语音聊天请求观察者
        imc().getTransDataListener().setRealTimeVoiceChatRequestForNotIntChatUIObserver(null);
    }


    //----------------------------- APP 异常自救代码 START
    /**
     * 关于APP异常自救的原因、方案、实现逻辑等，请见 {@link MyApplication#appHearthCheckFlag} 字段的详细说明。
     *
     * @return true表示APP现场处于非正常状态，否则表示正常状态
     */
    private boolean appHearthCheckInvalid() {
        try{
            String className = getClass().getSimpleName();
            // 处于异常现场了
            if (MyApplication.appHearthCheckFlag == -1) {
                Log.w(TAG, "【APP异常现场检查-主】已在"+className+"中检测到APP异常现场，马上进" +
                        "入异常重启逻辑（即接力跳转到闪屏入口界面【第2/2步】）。。。");

                Context ctx = MyApplication.getInstance2();

                // 以下代码确保跳转到APP的主口界面（从而达到重启APP的效果）
                Intent i = ctx.getPackageManager().getLaunchIntentForPackage(ctx.getPackageName());
                // 没有FLAG_ACTIVITY_NEW_TASK这个flag，是无法借助Application实例启动activity的
                i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
                // 前往入口页
                ctx.startActivity(i);

                // 释放APP应用占用的资源(如去掉脏现场前的服务绑定、notification等等资源的释放)
                LoginActivity.systemExit(ctx, false);

                // 最后关闭本界面（本界面本身已处于脏现场中，能回到主入口界面就好了，不需要本界面了）
                finish();

                return true;
            }
            else {
                Log.d(TAG, "【APP异常现场检查-主】在"+className+"中未检测到APP异常现场，什么也不需要做！（MyApplication.appHearthCheckFlag="
                        +MyApplication.appHearthCheckFlag+"）");
            }
        }
        catch (Exception e){
            Log.w(TAG, e);
        }

        return false;
    }
    //----------------------------- APP 异常自救代码 END


    //----------------------------- 后台服务相关代码，以后会加入更多功能 START
    /** 后台服务对象（绑定RainbowChat后，确保RainbowChat能常驻内存，并
     * 在Android状态上显示出来，方便用户找到） */
    private GeniusService boundService;

    /** 绑定时需要使用的连接对象 */
    private ServiceConnection serviceConnection = new ServiceConnection() {

        public void onServiceConnected(ComponentName className, IBinder service) {
            // This is called when the connection with the service has beenestablished, giving us the service object we can use to
            // interact with the service.  Because we have bound to a explicitservice that we know is running in our own process, we can
            // cast its IBinder to a concrete class and directly access it.
            boundService = ((GeniusService.LocalBinder)service).getService();

            // Tell the user about this for our demo.
//			WidgetUtils.showToast(getApplicationContext(), "DEBUG：后台服务已连接上了.", ToastType.INFO);
        }

        public void onServiceDisconnected(ComponentName className) {
            // This is called when the connection with the service has beenunexpectedly disconnected -- that is, its process crashed.
            // Because it is running in our same process, we should neversee this happen.
            boundService = null;

            //注意：此此不能用FunctionListActivity.this而因用getApplicationContext(),因为本方法的调用是在FunctionListActivity.this
            // 对象被destroy时调用，所以如果用FunctionListActivity.this则会出错！（因为FunctionListActivity.this已经被销毁了）
//			WidgetUtils.showToast(getApplicationContext(), "DEBUG：与后台服务断开了连接.", ToastType.INFO);
        }
    };

    /**
     * 将本activity与后台服务绑定起来.
     */
    protected void doBindService() {
        //** 重要说明：Activity不应直接this.bindService(..)，应使用
        //   this.getApplicationContext().bindService(..)，否则将绑定不成功.独立使用时不会有这样的问题具体请见js留存的相关文档及说明.
        this.getApplicationContext().bindService(new Intent(this.getApplicationContext(), GeniusService.class), serviceConnection, Context.BIND_AUTO_CREATE);
    }

    /**
     * 解绑服务（服务将失去功能，随时会被系统回收）.
     */
    protected void doUnbindService() {
        try {
            this.getApplicationContext().unbindService(serviceConnection);
        } catch (Exception e) {
            Log.w(TAG, e);
        }
    }

    /**
     * 重写父类方法，以便在本activity被销毁时自动解绑后台服务.
     *
     * @see #doUnbindService()
     */
    @Override
    protected void onDestroy() {
        Log.i(TAG, "onDestroy？");

        // 清除观察者
        clearObservers();
        // 本activity被销毁就解绑服务（服务将失去功能，随时会被系统回收）
        doUnbindService();
        // 结束Activity&从RainbowChar的Activity管理器栈中移除（以便APP退出时即时释放）
        AppManager.getAppManager().removeActivity(this);

        super.onDestroy();
    }
    //----------------------------- 后台服务相关代码 END
}
